//
//  String.swift
//  CXBaseUtil
//
//  Created by 李旭峰 on 2021/2/26.
//

import Foundation
import CommonCrypto
import UIKit

public extension String {
  
    func slicing(_ from:Int,_ to:Int) -> String{
    let selfStr = self.description
    if selfStr.count <= max(from, 0) {
      return ""
    }
    let `to` = min(selfStr.count, to)
    let startIndex = selfStr.index(selfStr.startIndex, offsetBy: from)
    let endIndex = selfStr.index(selfStr.startIndex, offsetBy: to)
    let subStr = selfStr[startIndex..<endIndex]
    return String(subStr)
  }
  /// 字符串长度
    var length: Int {
    return self.count
  }
  
  /**
   截取数字字符串，小数位大于8位则截取小数8位后的数字
   
   - parameter string: 要截取的字符串
   
   - returns: 返回新的字符串
   */
    func subString(def:Int = 8) -> String{
    let stringArr = self.components(separatedBy: ".")
    var newString = ""
    if stringArr.count == 2 {
      if stringArr[1].length > def{
        newString = String(format: "%.\(def)f", (self.toDouble()))
      }else{
        newString = self
      }
      if newString.toDouble() == 0{
        newString = "0"
      }
    }else{
      newString = self
    }
    return newString
  }
  
  /**
   计算文字的高度
   
   - parameter font:
   - parameter size:
   
   - returns:
   */
    func textSizeWithFont(_ font: UIFont, constrainedToSize size:CGSize) -> CGSize {
    var textSize:CGSize!
    let newStr = NSString(string: self)
    if size.equalTo(CGSize.zero) {
      let attributes = [NSAttributedString.Key.font: font]
      textSize = newStr.size(withAttributes: attributes)
    } else {
      let option = NSStringDrawingOptions.usesLineFragmentOrigin
      let attributes = [NSAttributedString.Key.font: font]
      let stringRect = newStr.boundingRect(with: size, options: option, attributes: attributes, context: nil)
      textSize = stringRect.size
    }
    return textSize
  }
  
  // MARK: Trim API
  
  /// 去掉字符串前后的空格，根据参数确定是否过滤换行符
  ///
  /// - parameter trimNewline 是否过滤换行符，默认为false
  ///
  /// - returns:   处理后的字符串
    func trim(_ trimNewline: Bool = false) ->String {
    if trimNewline {
      return self.trimmingCharacters(in: .whitespacesAndNewlines)
    }
    
    return self.trimmingCharacters(in: .whitespaces)
  }
  
  /**
   * 去除字符串左右的空格和换行，直到左右都没有任何空格和换行或者变成空字符串了
   */
    func trimBlankSpaceAndLineFeeds() -> String {
    
    let result = self.trimmingCharacters(in: .whitespacesAndNewlines)
    
    if result.hasPrefix(" ") || result.hasSuffix(" ") || result.hasPrefix("\n") || result.hasSuffix("\n") {
      
      return result.trimBlankSpaceAndLineFeeds()
    } else {
      
      return result
    }
  }
  
  // MARK: Substring API
  
  /// 获取子串的起始位置。
  ///
  /// - parameter substring 待查找的子字符串
  ///
  /// - returns:  如果找不到子串，返回NSNotFound，否则返回其所在起始位置
    func location(_ substring: String) ->Int {
    return (self as NSString).range(of: substring).location
  }
  
  /// 根据起始位置和长度获取子串。
  ///
  /// - parameter location  获取子串的起始位置
  /// - parameter length    获取子串的长度
  ///
  /// - returns:  如果位置和长度都合理，则返回子串，否则返回nil
    func substring(_ location: Int, length: Int) ->String? {
    if location < 0 {
      return self.substring(0, length: length)
    }
    if location < 0 && location >= self.length {
      return nil
    }
    
    if length <= 0 || length > self.length {
      return nil
    }
    
    let startIndex = self.index(self.startIndex, offsetBy: location)
    let endIndex = self.index(startIndex, offsetBy: length)
    let subString = self[startIndex..<endIndex]
    
    return String(subString)
  }
  
  /// 根据下标获取对应的字符。若索引正确，返回对应的字符，否则返回nil
  ///
  /// - parameter index 索引位置
  ///
  /// - returns: 如果位置正确，返回对应的字符，否则返回nil
    subscript(index: Int) -> Character? {
    get {
      if let str = substring(index, length: 1) {
        return Character(str)
      }
      return nil
    }
  }
  
  /// 判断字符串是否包含子串。
  ///
  /// - parameter substring 子串
  ///
  /// - returns:  如果找到，返回true,否则返回false
    func isContain(_ substring: String) ->Bool {
    return (self as NSString).contains(substring)
  }
  
  // MARK: Alphanum API
  
  /// 判断字符串是否全是数字组成
  ///
  /// - returns:  若为全数字组成，返回true，否则返回false
    func isOnlyNumbers() ->Bool {
    let set = CharacterSet.decimalDigits.inverted
    let range = (self as NSString).rangeOfCharacter(from: set)
    let flag = range.location != NSNotFound
    return flag
  }
  
  /// 判断字符串是否全是字母组成
  ///
  /// - returns:  若为全字母组成，返回true，否则返回false
    func isOnlyLetters() ->Bool {
    let set = CharacterSet.letters.inverted
    let range = (self as NSString).rangeOfCharacter(from: set)
    
    return range.location != NSNotFound
  }
  
  /// 判断字符串是否全是字母和数字组成
  ///
  /// - returns:  若为全字母和数字组成，返回true，否则返回false
    func isAlphanum() ->Bool {
    let set = CharacterSet.alphanumerics.inverted
    let range = (self as NSString).rangeOfCharacter(from: set)
    
    return range.location != NSNotFound
  }
  
  // MARK: Validation API
  
  /// 判断字符串是否是有效的邮箱格式
  ///
  /// - returns:  若为有效的邮箱格式，返回true，否则返回false
    func isValidEmail() ->Bool {
    let regEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    let predicate = NSPredicate(format: "SELF MATCHES %@", regEx)
    
    return predicate.evaluate(with: self)
  }
  
  // MARK: Format API
  
  /**
   
   插入字符分隔字符串
   - parameter char:     要插入的字符
   - parameter interval: 间隔数
   */
    func insertCharByInterval(_ char: String, interval: Int) -> String {
    var text = self as NSString
    var newString = ""
    while (text.length > 0) {
      let subString = text.substring(to: min(text.length,interval))
      newString = newString + subString
      if (subString.length == interval) {
        newString = newString + char
      }
      text = text.substring(from: min(text.length,interval)) as NSString
    }
    return newString
  }
  
  //
    func isVideoPath() -> Bool {
    let tempStr = self.lowercased()
    return tempStr.hasSuffix(".mp4")
      || tempStr.hasSuffix(".mov")
      || tempStr.hasSuffix(".flv")
      || tempStr.hasSuffix(".3gp")
      || tempStr.hasSuffix(".avi")
      || tempStr.hasSuffix(".rm")
      || tempStr.hasSuffix(".rmvb")
      || tempStr.hasSuffix(".wmv")
  }
  // MARK: CAST TO OTHER TYPE API
  
  /// 转double
  ///
  /// - Parameters:
  ///   - def: 默认值
  ///   - decimal: 舍弃小数位精度
  /// - Returns:
    func toDouble(_ def: Double = 0.0, decimal: Int? = nil) -> Double {
    if !self.isEmpty {
      var doubleValue = Double(self) ?? def
      if let dec = decimal {
        doubleValue = doubleValue.f(places: dec)
      }
      return doubleValue
    } else {
      return def
    }
  }
  
    func toFloat(_ def: Float = 0.0) -> Float {
    if !self.isEmpty {
      return Float(self) ?? def
    } else {
      return def
    }
  }
  
    func toInt(_ def: Int = 0) -> Int {
    if !self.isEmpty {
      return Int(self)!
    } else {
      return def
    }
  }
  
    func toBool(_ def: Bool = false) -> Bool {
    if !self.isEmpty {
      let value = Int(self)!
      if value > 0 {
        return true
      } else {
        return false
      }
    } else {
      return def
    }
  }
  
  /// 根据文字内容，最大宽度，字体大小计算出文字所占的高度
    static func getStrHeight(text: NSString, width: CGFloat, font: UIFont = UIFont.systemFont(ofSize: 14)) -> CGFloat {
    
    let rect = text.boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context: nil)
    
    return ceil(rect.size.height)
  }
  
  /// 根据文字内容，最大高度，字体大小计算出文字所占的宽度
    static func getStrHeight(text: NSString, width: CGFloat, attributes: [NSAttributedString.Key : Any]?) -> CGFloat {
    
    let rect = text.boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
    
    return ceil(rect.size.height)
  }
  
  /// 根据文字内容，最大高度，字体大小计算出文字所占的宽度
    static func getStrWidth(text: NSString, height: CGFloat, font: UIFont = UIFont.systemFont(ofSize: 14)) -> CGFloat {
    
    let rect = text.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font : font], context: nil)
    
    return ceil(rect.size.width)
  }
  
  /// 判断输入的字符是否是emoji表情
    static func isEmoji(from: String) -> Bool{
    func disable_emoji(text:String) -> String{
      let regex = try? NSRegularExpression(pattern: "[^\\u0020-\\u007E\\u00A0-\\u00BE\\u2E80-\\uA4CF\\uF900-\\uFAFF\\uFE30-\\uFE4F\\uFF00-\\uFFEF\\u0080-\\u009F\\u2000-\\u201f\r\n]", options: NSRegularExpression.Options.caseInsensitive)
      
      let modifiedString = regex!.stringByReplacingMatches(in: text, options: NSRegularExpression.MatchingOptions(), range: NSMakeRange(0, text.utf16.count), withTemplate: "")
      
      return modifiedString
    }
    
    // 判断是不是系统键盘输入的数字➋➌➍➎➏➐➑➒，这种情况要放开
    let otherStr = "➋➌➍➎➏➐➑➒"
    if otherStr.range(of: from) != nil {
      return false
    } else {
      // 当输入的是表情，那么不进行替换
      return from != disable_emoji(text: from)
    }
  }
  
  /**
   金额格式化
   */
    func moneyFormat() -> String {
    
    let numberFormatter = NumberFormatter()
    numberFormatter.numberStyle = .decimal
    let number: NSNumber? = numberFormatter.number(from: self)
    
    guard let num = number else {
      return "-"
    }
    
    let formatter = NumberFormatter()
    
    formatter.positiveFormat = "###,##0.00"
    let result = formatter.string(from: num)
    
    return result == nil ? "" : (result ?? "")
  }
  
  /**
   整数每3位加一个逗号
   */
    func centryPriceFormat() -> String {
    
    var newStr = ""
    
    if self.contains(".") {
      
      // 拿到整数部分和小数部分
      let firstStr: String = self.components(separatedBy: ".").first ?? ""
      let secondStr: String = self.components(separatedBy: ".").last ?? ""
      
      // 存在.说明是小数整数
      for i in 1...firstStr.count {
        
        let index: Int = firstStr.count - i
        
        let subStr: String = firstStr.substring(index, length: 1) ?? ""
        
        if i % 3 == 0 && index != 0 {
          newStr = ",".appending(subStr).appending(newStr)
        } else {
          newStr = subStr.appending(newStr)
        }
      }
      
      newStr = newStr.appending(".").appending(secondStr)
      
    } else {
      
      // 不存在.说明是整数
      for i in 1...self.count {
        
        let index: Int = self.count - i
        
        let subStr: String = self.substring(index, length: 1) ?? ""
        
        if i % 3 == 0 && index != 0 {
          newStr = ",".appending(subStr).appending(newStr)
        } else {
          newStr = subStr.appending(newStr)
        }
      }
    }
    
    return newStr
  }
  
  /// 将正价字符串转成正价显示格式,例如: 55403.74 转成 55,403.74 并且小数点后面的数字的字体变小
    func getPriceAttrString(leftFont: UIFont, rightFont: UIFont) -> NSAttributedString {
    
    let resultStr = self
    
    // 将字符串转成attrStr
    let strs: [String] = resultStr.components(separatedBy: ".")
    
    let firstStr: String = strs.first ?? "-"
    
    if firstStr == "0" || strs.count == 1 {
      
      // 当前的数据小于1
      let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "\(resultStr)", attributes: [NSAttributedString.Key.font : leftFont, NSAttributedString.Key.foregroundColor: UIColor.white])
      
      return firstAttrStr
    } else {
      
      // 当前的数据大于1
      let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "\(strs.first ?? "-").", attributes: [NSAttributedString.Key.font : leftFont, NSAttributedString.Key.foregroundColor: UIColor.white])
      
      let secondAttrStr: NSAttributedString = NSAttributedString(string: "\(strs.last ?? "-")", attributes: [NSAttributedString.Key.font : rightFont, NSAttributedString.Key.foregroundColor: UIColor.white])
      
      firstAttrStr.append(secondAttrStr)
      
      return firstAttrStr
    }
  }
  
  /// 将制定的人民币字符串转成人民币显示格式,例如: 55403.74 转成 ¥55,403.74 并且小数点后面的数字的字体变小
    func getRMBAttrString1(leftFont: UIFont, rightFont: UIFont, textColor: UIColor) -> NSAttributedString {
    
    let resultStr = self
    
    // 将字符串转成attrStr
    let strs: [String] = resultStr.components(separatedBy: ".")
    
    //        let firstStr: String = strs.first ?? "-"
    
    if strs.count < 2 {
      
      // 当前的数据小于1
      let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "¥", attributes: [NSAttributedString.Key.font : rightFont, NSAttributedString.Key.foregroundColor: textColor])
      
      let secondAttrStr: NSAttributedString = NSAttributedString(string: resultStr, attributes: [NSAttributedString.Key.font : leftFont, NSAttributedString.Key.foregroundColor: textColor])
      
      firstAttrStr.append(secondAttrStr)
      
      return firstAttrStr
    } else {
      
      // 当前的数据大于1
      let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "¥", attributes: [NSAttributedString.Key.font : rightFont, NSAttributedString.Key.foregroundColor: textColor])
      
      let secondAttrStr: NSAttributedString = NSAttributedString(string: "\(strs.first ?? "-")", attributes: [NSAttributedString.Key.font : leftFont, NSAttributedString.Key.foregroundColor: textColor])
      
      let thirdAttrStr: NSAttributedString = NSAttributedString(string: ".\(strs.last ?? "-")", attributes: [NSAttributedString.Key.font : rightFont, NSAttributedString.Key.foregroundColor: textColor])
      
      firstAttrStr.append(secondAttrStr)
      firstAttrStr.append(thirdAttrStr)
      
      return firstAttrStr
    }
  }
  
  /// 交易所总览的cell币对左右的大小不一样,例如:ETH/USDT
    func getSubjectAttrString(color: UIColor = UIColor.init(hexStr: "0x7C8286")) -> NSAttributedString {
    
    // 将字符串转成attrStr
    let strs: [String] = self.components(separatedBy: "/")
    
    let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "\(strs.first ?? "-")/", attributes: [NSAttributedString.Key.font : FontAsset.PingFangSC_Regular.size(14.0), NSAttributedString.Key.foregroundColor: color])
    
    let secondAttrStr: NSAttributedString = NSAttributedString(string: "\(strs.last ?? "-")", attributes: [NSAttributedString.Key.font : FontAsset.PingFangSC_Semibold.size(10.0), NSAttributedString.Key.foregroundColor: color])
    
    firstAttrStr.append(secondAttrStr)
    
    return firstAttrStr
  }
  
  /// 交易所中币种数组cell币对左右的大小不一样,例如:ETH/USDT
    func getSymbolSubjectAttrString() -> NSAttributedString? {
    
    if self.isEmpty { return nil }
    
    let components = self.components(separatedBy: CharacterSet(charactersIn: "/^"))
    
    let attributedSubjectString = NSMutableAttributedString(string: components[0],
                                                            attributes: [NSAttributedString.Key.font: FontAsset.PingFangSC_Semibold.size(16.0),
                                                                         NSAttributedString.Key.foregroundColor: UIColor(hexLiteral: 0x4E5463)])
    
    if components.count > 1 {
      let attributedPaymenString = NSAttributedString(string: "/" + components[1],
                                                      attributes: [NSAttributedString.Key.font : FontAsset.PingFangSC_Regular.size(12.0), NSAttributedString.Key.foregroundColor: UIColor(hexLiteral: 0x4E5463)])
      attributedSubjectString.append(attributedPaymenString)
    }
    return attributedSubjectString
  }
  
  /// 今日订单币对左右的大小不一样,例如:ETH/USDT
    func getTodayOrderSubjectAttrString() -> NSAttributedString? {
    
    if self.isEmpty { return nil }
    
    let components = self.components(separatedBy: CharacterSet(charactersIn: "/^"))
    
    let attributedSubjectString = NSMutableAttributedString(string: components[0],
                                                            attributes: [NSAttributedString.Key.font: FontAsset.PingFangSC_Regular.size(15.0),
                                                                         NSAttributedString.Key.foregroundColor: UIColor(hexLiteral: 0x4E5463)])
    
    if components.count > 1 {
      let attributedPaymenString = NSAttributedString(string: "/" + components[1],
                                                      attributes: [NSAttributedString.Key.font : FontAsset.PingFangSC_Regular.size(12.0), NSAttributedString.Key.foregroundColor: UIColor(hexLiteral: 0x4E5463)])
      attributedSubjectString.append(attributedPaymenString)
    }
    return attributedSubjectString
  }
  
  /// top100顶部的三个视图中的最右边
    func getTop100IndexRightAttrString(textColor: UIColor) -> NSAttributedString {
    
    // 将字符串转成attrStr
    let strs: [String] = self.components(separatedBy: " ")
    
    let firstAttrStr: NSMutableAttributedString = NSMutableAttributedString(string: "\(strs.first ?? "-")", attributes: [NSAttributedString.Key.font : FontAsset.DINAlternate_Bold.size(20.0), NSAttributedString.Key.foregroundColor: textColor])
    
    let secondAttrStr: NSAttributedString = NSAttributedString(string: " \(strs.last ?? "-")", attributes: [NSAttributedString.Key.font : FontAsset.PingFangSC_Regular.size(14.0), NSAttributedString.Key.foregroundColor: textColor])
    
    firstAttrStr.append(secondAttrStr)
    
    return firstAttrStr
  }
  
  /// 获取制定字符的长度字符串，以英文为标准，数字为1个字符，中文为2个字符
    func getSubString(charCount: Int) -> String? {
    
    var result: String = ""
    var totalCount: Int = 0
    
    for (_, value) in self.enumerated() {
      
      var newCount: Int = 0
      
      if ("\u{4E00}" <= value  && value <= "\u{9FA5}") {
        newCount = 2
      } else {
        newCount = 1
      }
      
      if (totalCount + newCount) > charCount {
        return result
      }
      
      result.append(value)
      totalCount = totalCount + newCount
    }
    
    // 到了这里说明所有的字符加起来都没达到标准，输出所有的字符
    return self
  }
  
  /// 查看字符串是否小于等于指定字符个数，以英文为标准，数字为1个字符，中文为2个字符
    func isLessThenCharLength(charCount: Int) -> Bool {
    return self.getSubString(charCount: charCount) == self
  }
  
  /// 获取小数点后的位数
    func getLastCountAfterPoint() -> Int {
    
    // 首先判断传入的值能否转成数字，如果不能，则直接返回0
    guard let _ = Double(self) else {
      return 0
    }
    
    // 根据.拆分字符串，如果拆分后的数组个数不是2，直接返回0
    let arr: [String] = self.components(separatedBy: ".")
    guard arr.count == 2 else {
      return 0
    }
    
    return arr.last!.count
  }
  
  /// 图片字符串保护，这里如果有？，则将问号后面的都删除
    func getSafeUrlStr() -> String {
    if self.contains("?") {
      return self.components(separatedBy: "?").first ?? ""
    }
    
    return self
  }
  
    func analyseCnString() -> String {
    let charSet = CharacterSet.urlQueryAllowed as NSCharacterSet
    let mutSet = charSet.mutableCopy() as! NSMutableCharacterSet
    mutSet.addCharacters(in: "#")
    mutSet.addCharacters(in: "%")
    return self.addingPercentEncoding(withAllowedCharacters: mutSet as CharacterSet) ?? ""
  }
    func removeBothEndsSpaces() -> String {
    let tempSelf = self
    return tempSelf.trimmingCharacters(in: CharacterSet.whitespaces)
  }
}

// MARK: - 正则校验
public extension String {
    func isEmail() -> Bool {
    let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
    return emailTest.evaluate(with: self)
  }
  
    func isPhone() -> Bool {
    let phoneRegex = "^1\\d{10}$"
    let phoneTest = NSPredicate(format: "SELF MATCHES %@", phoneRegex)
    return phoneTest.evaluate(with: self)
  }
    func isSmsCode() -> Bool {
    let phoneRegex = "^\\d{6}$"
    let phoneTest = NSPredicate(format: "SELF MATCHES %@", phoneRegex)
    return phoneTest.evaluate(with: self)
  }
    func getNumber() -> String {
    let scanner = Scanner(string: self)
    scanner.scanUpToCharacters(from: CharacterSet.decimalDigits, into: nil)
    var number :Int = 0
    scanner.scanInt(&number)
    return String(number)
  }
    func isImagePath() -> Bool {
    if self.lowercased().hasSuffix(".jpg") {
      return true
    }
    return false
  }
    func isIdentityNo() -> Bool{
    if self.count <= 0 {
      return false
    }
    return true
  }
}

// MARK: - 加密
public extension String{
  
    var md5: String {
    let cStr = self.cString(using: String.Encoding.utf8);
    let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 16)
    CC_MD5(cStr!,(CC_LONG)(strlen(cStr!)), buffer)
    let md5String = NSMutableString();
    for i in 0 ..< 16{
      md5String.appendFormat("%02x", buffer[i])
    }
    free(buffer)
    return md5String as String
  }
}

public extension String {
    var decimal: NSDecimalNumber {
    let de = NSDecimalNumber.init(string: self)
    
    return de == NSDecimalNumber.notANumber ? NSDecimalNumber.init(string: "0") : de
  }
    func sizeWithConstrainedSize(size:CGSize, font:UIFont, lineSpacing:CGFloat) -> CGSize{
    var expectedSize = CGSize.zero
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineBreakMode = NSLineBreakMode.byWordWrapping
    paragraphStyle.lineSpacing = lineSpacing
    let attributes = [
      NSAttributedString.Key(rawValue: NSAttributedString.Key.font.rawValue):  font, NSAttributedString.Key.paragraphStyle : paragraphStyle
      ] as [NSAttributedString.Key : Any]
    
    expectedSize = self.boundingRect(with: size, options: NSStringDrawingOptions(rawValue: NSStringDrawingOptions.RawValue(UInt8(NSStringDrawingOptions.usesLineFragmentOrigin.rawValue) |
      UInt8(NSStringDrawingOptions.usesFontLeading.rawValue))), attributes: attributes , context: nil).size
    return CGSize(width: ceil(expectedSize.width), height: ceil(expectedSize.height))
  }
}

public extension NSMutableAttributedString {
  
  /// 为富文本追加字符串
  ///
  /// - Parameters:
  ///   - subString: 子字符串
  ///   - stingColor: 字体颜色
  ///   - font: 字体大小
  ///   - kern: 字间距
  ///   - lineSpace: 行间距
  ///   - action: 字体的点击事件，默认不添加
    func append(subString:String,stringColor:UIColor,font:UIFont,kern:CGFloat,lineSpace:CGFloat){
    if subString.count <= 0 {
      return
    }
    let string_01 = String(subString.substring(0, length: subString.count - 1) ?? "")
    let string_02 = String(subString.substring(subString.count - 1, length: 1) ?? "")
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = lineSpace
    
    var attributed_01:[NSAttributedString.Key:Any] = [:]
    attributed_01[NSAttributedString.Key.paragraphStyle] = style
    attributed_01[NSAttributedString.Key.font] = font
    attributed_01[NSAttributedString.Key.kern] = kern
    attributed_01[NSAttributedString.Key.foregroundColor] = stringColor
    
    var attributed_02:[NSAttributedString.Key:Any] = [:]
    attributed_02[NSAttributedString.Key.paragraphStyle] = style
    attributed_02[NSAttributedString.Key.font] = font
    attributed_02[NSAttributedString.Key.foregroundColor] = stringColor
    
    let attributeString = NSMutableAttributedString()
    attributeString.append(NSAttributedString(string: string_01, attributes: attributed_01))
    attributeString.append(NSAttributedString(string: string_02, attributes: attributed_02))
    self.append(attributeString)
  }
    func appendEmpty(withHeight lineHeight:CGFloat){
    let string = "*\n"
    
    let style = NSMutableParagraphStyle()
    style.lineSpacing = 0.0
    style.minimumLineHeight = lineHeight
    style.maximumLineHeight = lineHeight
    
    var attributed:[NSAttributedString.Key:Any] = [:]
    attributed[NSAttributedString.Key.paragraphStyle] = style
    attributed[NSAttributedString.Key.font] = FontAsset.PingFangSC_Regular.size(9.0)
    attributed[NSAttributedString.Key.kern] = 0.0
    #if DEBUG
    attributed[NSAttributedString.Key.foregroundColor] = UIColor.purple
    #else
    attributed[NSAttributedString.Key.foregroundColor] = UIColor.clear
    #endif
    let attributeString = NSAttributedString(string: string, attributes: attributed)
    
    self.append(attributeString)
  }
}

public extension String {
    func oss(h:CGFloat,w:CGFloat) -> String {
        if self.length <= 0 {
            return ""
        }
        return "\(self)?x-oss-process=image/resize,m_fixed,h_\(h),w_\(w)"
    }
    func oss() -> String {
        if self.length <= 0 {
            return ""
        }
        return "\(self)?x-oss-process=image/resize,m_fixed,h_150,w_150"
    }
    func oss_level01() -> String {
        if self.length <= 0 {
            return ""
        }
        return "\(self)?x-oss-process=image/resize,m_fixed,h_500,w_500"
    }
}

